Skip to content

fix: correct SnapTrade cash activity signs#1634

Open
sure-admin wants to merge 2 commits intomainfrom
fix/snaptrade-cash-signs-1242
Open

fix: correct SnapTrade cash activity signs#1634
sure-admin wants to merge 2 commits intomainfrom
fix/snaptrade-cash-signs-1242

Conversation

@sure-admin
Copy link
Copy Markdown
Collaborator

@sure-admin sure-admin commented May 1, 2026

Summary

  • fix SnapTrade cash activity sign normalization to match Sure conventions
  • store inflows as negative amounts and outflows as positive amounts
  • add coverage for dividends, contributions, withdrawals, and transfers

Closes #1242

Details

Sure uses:

  • negative amounts for inflows / income
  • positive amounts for outflows / expenses

SnapTrade cash activity normalization was inverted for dividends and other cash movements. This patch corrects:

  • DIVIDEND, DIV, CONTRIBUTION, TRANSFER_IN, INTEREST, CASH -> negative
  • WITHDRAWAL, TRANSFER_OUT, FEE, TAX -> positive

Testing

  • not run locally in this OpenClaw container because Ruby is unavailable here
  • CI should validate the updated SnapTrade activity processor tests

Summary by CodeRabbit

  • Bug Fixes
    • Fixed cash transaction sign handling so deposits, withdrawals, dividends and contributions display with the correct positive/negative amounts for accurate balances.
    • Improved transfer processing so inbound/outbound transfers are recorded and labeled consistently.

@brin-security-scanner brin-security-scanner Bot added the contributor:flagged Contributor flagged for review by trust analysis. label May 1, 2026
@brin-security-scanner
Copy link
Copy Markdown

brin-security-scanner Bot commented May 1, 2026

⚠️ Contributor Trust Check — Review Recommended

This contributor's profile shows patterns that may warrant additional review. This is based on their GitHub activity, not the contents of this PR.

sure-admin · Score: 77/100

Dimension breakdown
Dimension Score What it measures
Identity 45 Account age, contribution history, GPG keys, org memberships
Behavior 90 PR patterns, unsolicited contribution ratio, activity cadence
Content 100 PR body substance, issue linkage, contribution quality
Graph 30 Cross-repo trust, co-contributor relationships

Analyzed by Brin · Full profile

@brin-security-scanner brin-security-scanner Bot added the pr:verified PR passed security analysis. label May 1, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 1, 2026

📝 Walkthrough

Walkthrough

The normalize_cash_amount logic in Snaptrade activities was changed: cash outflows (withdrawals, transfer outs) now normalize to positive amounts, and cash inflows (dividends, contributions, transfer ins) now normalize to negative amounts. Corresponding tests were updated to match this sign convention.

Changes

Cohort / File(s) Summary
Processor change
app/models/snaptrade_account/activities_processor.rb
Flipped sign convention in normalize_cash_amount: outflows use amount.abs (positive), inflows use -amount.abs (negative).
Snaptrade activities tests
test/models/snaptrade_account/activities_processor_test.rb
Updated assertions to expect negative amounts for inflows (dividend, contribution, transfer_in) and positive for outflows (withdrawal, transfer_out). Added transfer tests verifying labels and amounts.
Processor integration test
test/models/snaptrade_account_processor_test.rb
Adjusted withdrawal normalization expectation to assert a positive numeric amount (1000.00) instead of negative.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • luckyPipewrench
  • jjmata

Poem

🐰 I flipped the signs and hopped about,
Inflows wear minus, outflows shout out.
Tests now match the rabbit's art,
Balance sheets smile and charts take part.
Hooray — the ledger's doing its part! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: correcting SnapTrade cash activity sign handling to match Sure conventions.
Linked Issues check ✅ Passed The PR correctly implements sign normalization for SnapTrade activities: inflows (dividends, contributions, transfers in) now store as negative and outflows (withdrawals, transfers out) as positive, directly addressing issue #1242.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing SnapTrade cash activity sign normalization and adding corresponding test coverage as required by issue #1242.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/snaptrade-cash-signs-1242

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
Review rate limit: 6/8 reviews remaining, refill in 7 minutes and 54 seconds.

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
app/models/snaptrade_account/activities_processor.rb (1)

247-256: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Generic TRANSFER type is not normalized by normalize_cash_amount.

TRANSFER is present in CASH_TYPES (line 45) and maps to "Transfer" in the label table, but it falls through to else amount in normalize_cash_amount. SnapTrade's sign convention is that a positive amount represents gaining cash and a negative amount represents spending cash. If a broker emits a bare TRANSFER with a positive amount (cash received), it will be stored as positive in Sure—the wrong sign for an inflow. This is the same class of bug being fixed for TRANSFER_IN/TRANSFER_OUT.

🐛 Proposed fix
     when "CONTRIBUTION", "TRANSFER_IN", "DIVIDEND", "DIV", "INTEREST", "CASH"
-      -amount.abs  # Money in should be negative in Sure
+      -amount.abs  # Money in should be negative in Sure
+    when "TRANSFER"
+      # Direction is ambiguous; normalize using SnapTrade's own sign:
+      # positive = inflow → negate; negative = outflow → negate to positive
+      -amount

Alternatively, if TRANSFER is always directional via its sign, simply negate it:

+    when "TRANSFER"
+      -amount
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/models/snaptrade_account/activities_processor.rb` around lines 247 - 256,
The normalize_cash_amount method fails to handle the generic "TRANSFER" type;
update normalize_cash_amount (in
app/models/snaptrade_account/activities_processor.rb) to treat "TRANSFER" the
same as "TRANSFER_IN" by returning -amount.abs for inflows (so add "TRANSFER" to
the when branch that currently lists "CONTRIBUTION", "TRANSFER_IN", "DIVIDEND",
"DIV", "INTEREST", "CASH"); this ensures bare TRANSFER values are normalized to
the correct sign in Sure.
test/models/snaptrade_account/activities_processor_test.rb (1)

115-132: ⚠️ Potential issue | 🟠 Major

Stale assertion in test/models/snaptrade_account_processor_test.rb will break CI.

The test at line 213 "activities processor normalizes withdrawal as negative amount" contains an assertion at line 231 (assert tx_entry.amount.negative?) that contradicts the PR's new normalization behavior. After this change, WITHDRAWAL is normalized to amount.abs (positive), causing the assertion to fail.

Fix by updating the test name and assertion:

Required changes
-  test "activities processor normalizes withdrawal as negative amount" do
+  test "activities processor normalizes withdrawal as positive outflow amount" do
     ...
-    assert tx_entry.amount.negative?
+    assert tx_entry.amount.positive?
   end
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/models/snaptrade_account/activities_processor_test.rb` around lines 115
- 132, Update the test that still asserts a withdrawal is negative: rename the
test description from the old "normalizes withdrawal as negative amount" to
reflect the new normalization (e.g., "normalizes withdrawal as positive amount")
and replace the failing assertion `assert tx_entry.amount.negative?` with an
assertion that the amount is positive/absolute (for example, `assert_equal
tx_entry.amount, tx_entry.amount.abs` or `assert tx_entry.amount > 0`) so it
matches the new normalization behavior in SnaptradeAccount::ActivitiesProcessor.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@app/models/snaptrade_account/activities_processor.rb`:
- Around line 247-256: The normalize_cash_amount method fails to handle the
generic "TRANSFER" type; update normalize_cash_amount (in
app/models/snaptrade_account/activities_processor.rb) to treat "TRANSFER" the
same as "TRANSFER_IN" by returning -amount.abs for inflows (so add "TRANSFER" to
the when branch that currently lists "CONTRIBUTION", "TRANSFER_IN", "DIVIDEND",
"DIV", "INTEREST", "CASH"); this ensures bare TRANSFER values are normalized to
the correct sign in Sure.

In `@test/models/snaptrade_account/activities_processor_test.rb`:
- Around line 115-132: Update the test that still asserts a withdrawal is
negative: rename the test description from the old "normalizes withdrawal as
negative amount" to reflect the new normalization (e.g., "normalizes withdrawal
as positive amount") and replace the failing assertion `assert
tx_entry.amount.negative?` with an assertion that the amount is
positive/absolute (for example, `assert_equal tx_entry.amount,
tx_entry.amount.abs` or `assert tx_entry.amount > 0`) so it matches the new
normalization behavior in SnaptradeAccount::ActivitiesProcessor.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c7cb5bd6-10f4-45fb-a150-c27ad301585a

📥 Commits

Reviewing files that changed from the base of the PR and between 268f5ae and bd8da44.

📒 Files selected for processing (2)
  • app/models/snaptrade_account/activities_processor.rb
  • test/models/snaptrade_account/activities_processor_test.rb

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
test/models/snaptrade_account_processor_test.rb (1)

231-231: ⚡ Quick win

Use exact decimal assertion for monetary values

At Line 231, converting to Float can mask precision issues in money tests. Assert the decimal value directly instead.

Proposed change
-    assert_equal 1000.00, tx_entry.amount.to_f
+    assert_equal BigDecimal("1000.00"), tx_entry.amount
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/models/snaptrade_account_processor_test.rb` at line 231, Replace the
float conversion assertion that masks precision—change the assertion that
currently calls assert_equal 1000.00, tx_entry.amount.to_f to assert the exact
decimal value instead (e.g., compare against BigDecimal("1000.00") or the
model's money type directly). Update the assertion to use tx_entry.amount (or
tx_entry.amount.to_d) and compare to a BigDecimal literal so the test checks
exact monetary precision.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@test/models/snaptrade_account_processor_test.rb`:
- Line 231: Replace the float conversion assertion that masks precision—change
the assertion that currently calls assert_equal 1000.00, tx_entry.amount.to_f to
assert the exact decimal value instead (e.g., compare against
BigDecimal("1000.00") or the model's money type directly). Update the assertion
to use tx_entry.amount (or tx_entry.amount.to_d) and compare to a BigDecimal
literal so the test checks exact monetary precision.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 44ce7b8c-99f7-455c-ae28-b4253e783321

📥 Commits

Reviewing files that changed from the base of the PR and between bd8da44 and 6ebdbfa.

📒 Files selected for processing (1)
  • test/models/snaptrade_account_processor_test.rb

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr:verified PR passed security analysis.

Development

Successfully merging this pull request may close these issues.

Bug: SnapTrade Dividends importing as negatives

2 participants